/* 
 *  <copyright file="CGuid.cs" company="Wesley Jowitt">
 *  
 *  SobrietyEngine: Copyright (c) 2011 Wesley Jowitt
 *  
 *  This software is distributed under a software license.
 *   * As of the creation time of this file, the license in use is the Microsoft Permissive License (Ms-PL) 
 *    * The license can be viewed at:
 *     * License.Txt in the root folder of this project
 *      * http://sobrietyengine.codeplex.com/license
 *       * http://www.microsoft.com/opensource/licenses.mspx
 *       
 *  </copyright>
 *   */

using System;
using System.Collections.Generic;
using System.Text;

using SobrietyEngine.Actor;

namespace SobrietyEngine.Guids
{   
    //TODO: implement ref counting for guids.
    //TODO: implement idisposable - we have to remove ourselves from the guid manager!!!
    /// <summary>
    /// Item used to give args unique ID's and link them to scriptable names
    /// </summary>
    public class CGuid
    {
        /// <summary>
        /// Gets the value assigned by the GuidGameService
        /// </summary>
        public Int32 Value { get; private set; }
        /// <summary>
        /// Gets a value indicating whether this args has name.
        /// </summary>
        /// <value>
        ///   <c>true</c> if this args has name; otherwise, <c>false</c>.
        /// </value>
        public Boolean HasName { get; private set; }
        /// <summary>
        /// Gets the name assigned to this guid, if it has one.
        /// </summary>
        public String Name { get; private set; }



        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this args.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this args.
        /// </returns>
        public override string ToString()
        {
            return "CGuid( " + Value.ToString() + ", " + Name + ")";
        }

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <returns>
        /// The result of the operator.
        /// </returns>
        public static bool operator ==(CGuid x, CGuid y)
        {            
            if ((object)x == null && (object)y == null)
                return true;   
         
            if ((object)x != null && (object)y != null)
            {
                if(x.Value == y.Value)
                    return true;
                return false;
            }

            return false;
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <returns>
        /// The result of the operator.
        /// </returns>
        public static bool operator !=(CGuid x, CGuid y)
        {
            return !(x == y);
        }

        /// <summary>
        /// Returns a hash code for this args, based soley on the unique value assigned by the GuidGameService.
        /// </summary>
        /// <returns>
        /// A hash code for this args, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            return Value.GetHashCode();
        }

        /// <summary>
        /// Initializes a new args of the <see cref="CGuid"/> class, with a value of -1. Should
        /// not be used outside of the GuidGameService. Instead, use the static create methods
        /// </summary>
        public CGuid()
        {
            Value = -1;//-1 is unassigned
            HasName = false;
            Name = String.Empty;
        }
        
        /// <summary>
        /// Initializes a new args of the <see cref="CGuid"/> class, copying the guid
        /// </summary>
        /// <param name="guid">The GUID.</param>
        public CGuid(CGuid guid)
        {
            Value = guid.Value;
            Name = guid.Name;
            HasName = guid.HasName;
        }

        /// <summary>
        /// Clears this args. Used for pooling GUidGameService
        /// </summary>
        public void Clear()
        {
            Value = -1;
            Name = String.Empty;
            HasName = false;
        }

        /// <summary>
        /// Attempts to attach a name to this guid, if one doesnt already exist
        /// </summary>
        /// <param name="name">The name.</param>
        public void NameGuid(String name)
        {
            //attempt to name this guid
            Guids.GuidGameService.GetSingleton().CreateNameForGuid(this, name);
        }

        /// <summary>
        /// Sets the specified Guid values, used in pooling.
        /// </summary>
        /// <param name="val">The val.</param>
        /// <param name="name">The name.</param>
        /// <param name="hasName">if set to <c>true</c> [has name].</param>
        public void Set(Int32 val, String name, Boolean hasName)
        {
            this.Value = val;
            this.Name = name;
            this.HasName = hasName;
        }
        /// <summary>
        /// Creates the specified GUID thats name is object name and resolves to obj using GuidGameService pool
        /// </summary>
        /// <param name="objectName">Name of the object.</param>
        /// <param name="obj">The obj.</param>
        public static CGuid Create(String objectName, Object obj)
        {
            return Guids.GuidGameService.GetSingleton().CreateGuid(objectName, obj);
        }
        /// <summary>
        /// Creates the a guid that links to the specified obj using GuidGameService pool
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <returns></returns>
        public static CGuid Create(Object obj)
        {
            return Guids.GuidGameService.GetSingleton().CreateGuid(obj);
        }
        /// <summary>
        /// Creates the empty GUID using GuidGameService pool
        /// </summary>
        /// <returns></returns>
        public static CGuid CreateEmpty()
        {
            return Guids.GuidGameService.GetSingleton().CreateEmptyGuid();
        }


        /// <summary>
        /// Gets the GUID with the name 'name' if it exists.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public static CGuid GetGuid(String name)
        {
            return Guids.GuidGameService.GetSingleton().GetGuidFromName(name);
        }

        /// <summary>
        /// Resolves this args to the object the value is assigned to.
        /// </summary>
        /// <returns></returns>
        public Object Resolve()
        {
            return Guids.GuidGameService.GetSingleton().GetGuidObject(this);
        }

        /// <summary>
        /// Resolves this args to strType specified.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T Resolve<T>()
        {
            return (T)Guids.GuidGameService.GetSingleton().GetGuidObject(this);
        }


        /// <summary>
        /// Removes this args and returns the Guid object to the pool
        /// </summary>
        public void Remove()
        {
            Guids.GuidGameService.GetSingleton().RemoveGuid(this);
        }

    }
}
